import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import opennlp.tools.namefind.NameFinderME;
import opennlp.tools.namefind.TokenNameFinderModel;
import opennlp.tools.postag.POSModel;
import opennlp.tools.postag.POSTaggerME;
import opennlp.tools.sentdetect.SentenceDetectorME;
import opennlp.tools.sentdetect.SentenceModel;
import opennlp.tools.tokenize.Tokenizer;
import opennlp.tools.tokenize.TokenizerME;
import opennlp.tools.tokenize.TokenizerModel;
import opennlp.tools.util.Span;

public class GeneraTagRDF {

	/**
	 * @param args
	 * @throws FileNotFoundException 
	 */
	public static void main(String[] args) throws FileNotFoundException {
			
		
		String tag  = "I know Maria, John Smith and Adelaide Adele Brown, very good people, Mary Connor Junior Garcia. There is a big car that looks fine, running fast in a busy street that looks strange. There are a beautiful blonde woman running in the large street. He's playing well";
		
		/**DIVIDE IL TAG IN SENTENZE*/
		SentenceModel model = null;
		//carica il sentence model
		InputStream modelIn = new FileInputStream("src/resources/en-sent.bin");
		try {
			  model = new SentenceModel(modelIn);
			}
			catch (IOException e) {
			  e.printStackTrace();
			}
			finally {
			  if (modelIn != null) {
			    try {
			      modelIn.close();
			    }
			    catch (IOException e) {
			    }
			  }
			}
		//istanzia il sentence detector
		SentenceDetectorME sentenceDetector = new SentenceDetectorME(model);
		//ritorna un array di stringhe che descrive le sentenze nel tag
		String sentencesTag[] = sentenceDetector.sentDetect(tag);		
		//cicla sulle sentenze
		int cont = 0;
		while (sentencesTag.length != cont){
			System.out.println(sentencesTag[cont]);
			cont ++;
		}
		
		/**DIVIDE LA SENTENZA IN TOKEN*/
		//carica il tokenizer model
		TokenizerModel model2 = null;
		InputStream modelIn2 = new FileInputStream("src/resources/en-token.bin");
		try {
		  model2 = new TokenizerModel(modelIn2);
		}
		catch (IOException e) {
		  e.printStackTrace();
		}
		finally {
		  if (modelIn2 != null) {
		    try {
		      modelIn2.close();
		    }
		    catch (IOException e) {
		    }
		  }
		}
		//istanzia il tokenizer detector
		Tokenizer tokenizer = new TokenizerME(model2);
		//ritorna un array di stringhe che descrive i token nella sentenza
		String tokensSentence[] = tokenizer.tokenize(sentencesTag[1]); //lavoro sulla sentenza che voglio
		//double tokenProbs[] = tokenizer.getTokenProbabilities();
		System.out.println("numero di token nella sentenza: "+tokensSentence.length);
		//cicla sui token della sentenza
		int cont2 = 0;
		while (tokensSentence.length != cont2){
			System.out.println(tokensSentence[cont2]);
			cont2 ++;
		}
		
		/**RICONOSCITORE DI NOMI DI PERSONE*/
		//TODO SOSTITUIRLE CON MENO GENERICI 'UOMO' E 'DONNA'
		//carica il person model
		TokenNameFinderModel model3 = null;
		InputStream modelIn3 = new FileInputStream("src/resources/en-ner-person.bin");
		try {
		  model3 = new TokenNameFinderModel(modelIn3);
		}
		catch (IOException e) {
		  e.printStackTrace();
		}
		finally {
		  if (modelIn3 != null) {
		    try {
		      modelIn3.close();
		    }
		    catch (IOException e) {
		    }
		  }
		}
		//istanzia il name finder
		NameFinderME nameFinder = new NameFinderME(model3);		
		Span nameSpans[] = nameFinder.find(tokensSentence);
		System.out.println("persone nella frase: "+nameSpans.length);
		//cicla su ogni nome (composto anche da più parole) nella frase			
		ArrayList<String> arrayListTokensSentence = new ArrayList<String>(Arrays.asList(tokensSentence));
		for (int cont3 = 0 ; nameSpans.length > cont3 ; cont3++){			
			System.out.println(nameSpans[cont3]);
			int wordsInName = nameSpans[cont3].getEnd() - nameSpans[cont3].getStart();		
			//rimuove i nomi delle persone e le sostituisce con un generico 'person'			
			for (int i = 0; i < wordsInName; i++){				
				if (i == (wordsInName - 1)){
					arrayListTokensSentence.set(nameSpans[cont3].getStart()+i, "person");								
				}else{
					arrayListTokensSentence.set(nameSpans[cont3].getStart()+i, "@");										
				}
			}			
		}
		for (int cont5 = 0 ; arrayListTokensSentence.size() > cont5 ; cont5++){
			if (arrayListTokensSentence.get(cont5).equals("@")){
				arrayListTokensSentence.remove(cont5);
				cont5--;
			}				
		}
		//riconverto l'ArrayList in un array di Stringhe, che conterrà 'Person' invece dei nomi 
		tokensSentence = arrayListTokensSentence.toArray(new String[arrayListTokensSentence.size()]);		
		
		/**POS TAGGER*/
		//carica il POS tokenizer
		POSModel model4 = null;
		InputStream modelIn4 = null;
		try {
		  modelIn4 = new FileInputStream("src/resources/en-pos-maxent.bin");
		  model4 = new POSModel(modelIn4);
		}
		catch (IOException e) {
		  // Model loading failed, handle the error
		  e.printStackTrace();
		}
		finally {
		  if (modelIn4 != null) {
		    try {
		      modelIn4.close();
		    }
		    catch (IOException e) {
		    }
		  }
		}
		//istanzia il POS tokenizer
		POSTaggerME tagger = new POSTaggerME(model4);
		//ritorna un array di stringhe che descrive i POS tokenized della nostra sentenza, corrispondenti in base all'indice dell'array
		String POStags[] = tagger.tag(tokensSentence);
		
		//cicla sulle sentenze e POS tagger
		int cont4 = 0;
		while (tokensSentence.length != cont4){
			System.out.println(tokensSentence[cont4]+" - "+POStags[cont4]);			
			cont4 ++;
		}
		
		
		/**FILTRO*/
		
		//if ( (!arrayListPOStags.contains("NN")) && (!arrayListPOStags.contains("NNS")))
		//	System.out.println("ATTENZIONE! LA SENTENZA NON CONTIENE SOGGETTI!");
		
		//stampo i nuovi array filtrati
		String subject = "";
		String predicateSubject = "";		
		ArrayList<String> adjectiveSubject = new ArrayList<String>(); //lista degli aggettivi del soggetto
		String object = "";
		String predicateObject = "";
		ArrayList<String> adjectiveObject = new ArrayList<String>(); //lista degli aggettivi dell'oggetto
		boolean obj = false; //valuta se si è già presentato il soggetto, e quindi il noun diventa un oggetto
		boolean predicateObj = false; //valuta se si è già presentato il soggetto, e quindi il noun diventa un oggetto
		int cont6 = 0;
		while (POStags.length != cont6){
			if (POStags[cont6].equals("EX")){ //ignoro il there esistenziale (there is, there are) e il verbo che lo segue
				cont6 ++;
			}
			//Soggetto oppure Oggetto
			else if (POStags[cont6].equals("NN") || POStags[cont6].equals("NNS") || POStags[cont6].equals("PRP")){ 
				if (POStags[cont6].equals("PRP"))
					tokensSentence[cont6] = "person";
				if (!obj){
					subject = tokensSentence[cont6];
					obj = true;	
				}else
					object = tokensSentence[cont6];				
			}			
			//Verbi - ignoro i verbi seguiti da aggettivo o da un altro verbo (ad es He "is" playing)
			else if( (cont6+1 != POStags.length || cont6 == POStags.length) && ( !POStags[cont6+1].equals("JJ") && !POStags[cont6+1].equals("JJS") && !POStags[cont6+1].equals("VB") && !POStags[cont6+1].equals("VBD") && !POStags[cont6+1].equals("VBG") && !POStags[cont6+1].equals("VBN") && !POStags[cont6+1].equals("VBP") && !POStags[cont6+1].equals("VBZ") ) && (POStags[cont6].equals("VB") || POStags[cont6].equals("VBD") || POStags[cont6].equals("VBG") || POStags[cont6].equals("VBN") || POStags[cont6].equals("VBP") || POStags[cont6].equals("VBZ"))){
				if (!predicateObj){
					predicateSubject = tokensSentence[cont6];
					predicateObj = true;
				}else
					predicateObject = tokensSentence[cont6];
			}
			//Aggettivi
			else if(POStags[cont6].equals("JJ") || POStags[cont6].equals("JJS")){
				//se l'aggettivo viene appena prima del noun, si riferisce a quel noun (memorizza anche più aggettivi)
				if ((cont6+1 != POStags.length) && (POStags[cont6+1].equals("NN") || POStags[cont6+1].equals("NNS") || POStags[cont6+1].equals("JJ") || POStags[cont6+1].equals("JJS"))){ 
					System.out.println("aggettivo prima del noun: "+tokensSentence[cont6]);
					if (!obj){
						adjectiveSubject.add(tokensSentence[cont6]);
						System.out.println("al soggetto");}
					else{
						adjectiveObject.add(tokensSentence[cont6]);
						System.out.println("all'oggetto");}
				//se l'aggettivo viene appena dopo un verbo, si riferisce al noun relativo a quel verbo||
				}else if((cont6-1 >= 0) && (POStags[cont6-1].equals("VB") || POStags[cont6-1].equals("VBD") || POStags[cont6-1].equals("VBG") || POStags[cont6-1].equals("VBN") || POStags[cont6-1].equals("VBP") || POStags[cont6-1].equals("VBZ"))){ 
					System.out.println("aggettivo dopo un certo verbo: "+tokensSentence[cont6]);
					if (object.equals("")){
						System.out.println("al soggetto");
						adjectiveSubject.add(tokensSentence[cont6]);}
					else{
						adjectiveObject.add(tokensSentence[cont6]);
						System.out.println("all'oggetto");}
				}
			}
			System.out.println(tokensSentence[cont6]);
			System.out.println(POStags[cont6]);
			cont6 ++;
		}
		
		
		
		
		
		/**CHUNKER
		//carica il chunker (raggruppa insiemi correlati di parole)
		InputStream modelIn5 = null;
		ChunkerModel model5 = null;

		try {
		  modelIn5 = new FileInputStream("src/resources/en-chunker.bin");
		  model5 = new ChunkerModel(modelIn5);
		} catch (IOException e) {
		  // Model loading failed, handle the error
		  e.printStackTrace();
		} finally {
		  if (modelIn5 != null) {
		    try {
		      modelIn5.close();
		    } catch (IOException e) {
		    }
		  }
		}
		//istanzia il chunker
		ChunkerME chunker = new ChunkerME(model5);
		//riceve come parametri i tokens e i relativi POS tags, restituisce un array di stringhe con un chunk tag in relazione posizionale con i token
		String chunks[] = chunker.chunk(tokensSentence, POStags);
		
		int cont6 = 0;
		while (chunks.length != cont6){
			System.out.println(chunks[cont6]);
			cont6 ++;
		}
		*/

	
		
		
		
		System.out.println("subject: "+subject);
		System.out.println("predicateSubject: "+predicateSubject);
		System.out.println("adjectiveSubject: "+adjectiveSubject);
		System.out.println("object: "+object);
		System.out.println("predicateObject: "+predicateObject);
		System.out.println("adjectiveObject: "+adjectiveObject);
		
		
		BufferedWriter bufferedWriter = null;
        try {
            
            //
            bufferedWriter = new BufferedWriter(new FileWriter("/home/obi/prova.rdf",false));
            
            //
            bufferedWriter.write("<?xml version=\"1.0\"?>"); bufferedWriter.newLine();
            bufferedWriter.write("<rdf:RDF"); bufferedWriter.newLine();
            bufferedWriter.write("xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\""); bufferedWriter.newLine();
            bufferedWriter.write("xmlns:geo=\"http://www.w3.org/2003/01/geo/wgs84_pos#\""); bufferedWriter.newLine();
            bufferedWriter.write("xmlns:mio=\"http://www.ambiance.com/ns#\">"); bufferedWriter.newLine();
            bufferedWriter.write("<rdf:Description rdf:nodeID=\"tag1\">"); bufferedWriter.newLine();
            bufferedWriter.write("<geo:lat>51.5215864</geo:lat>"); bufferedWriter.newLine();
            bufferedWriter.write("<geo:long>-0.1177649</geo:long>"); bufferedWriter.newLine();                        
            bufferedWriter.write("<mio:noun>"+subject+"</mio:noun>"); bufferedWriter.newLine();
            bufferedWriter.write("<mio:predicate>"+predicateSubject+"</mio:predicate>"); bufferedWriter.newLine();
            bufferedWriter.write("<mio:object>"+object+"</mio:object>"); bufferedWriter.newLine();
            bufferedWriter.write("<mio:adjective>"+adjectiveSubject+"</mio:adjective>"); bufferedWriter.newLine();
            bufferedWriter.write("</rdf:Description>"); bufferedWriter.newLine();
            bufferedWriter.write("</rdf:RDF>"); bufferedWriter.newLine();
            
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            //Close the BufferedWriter
            try {
                if (bufferedWriter != null) {
                    bufferedWriter.flush();
                    bufferedWriter.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        System.out.println("RDF generato");

	}

}
